package io.kiki.sba.registry.server.data_store.bootstrap;

import io.kiki.sba.registry.server.shared.config.CommonConfig;
import io.kiki.sba.registry.server.shared.config.ServerShareConfig;
import io.kiki.sba.registry.server.shared.env.ServerEnv;
import io.kiki.sba.registry.util.OsUtils;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Collection;


@ConfigurationProperties(prefix = ServerConfig.PRE_FIX)
public class ServerConfig implements ServerShareConfig {

    public static final String PRE_FIX = "data.server";

    @Setter
    @Getter
    private int port = 9620;
    // data change notify
    @Getter
    @Setter
    private int notifyPort = 9623;
    @Getter
    @Setter
    private int syncDataPort = 9621;
    @Getter
    @Setter
    private int syncDataConnNum = 3;

    @Getter
    @Setter
    private int syncSessionPort = 9602;
    @Getter
    @Setter
    private int syncSessionConnNum = 6;
    @Getter
    @Setter
    private int metaServerPort = 9611;

    @Getter
    @Setter
    private int httpServerPort = 9622;

    @Getter
    @Setter
    private int notifyExecutorPoolSize = OsUtils.getCpuCount() * 10;

    @Getter
    @Setter
    private int notifyExecutorQueueSize = 10000;

    @Getter
    @Setter
    private int notifyRetryQueueSize = 10000;

    @Getter
    @Setter
    private int notifyMaxItems = 400;

    @Getter
    @Setter
    private int notifyIntervalMillis = 500;

    @Getter
    @Setter
    private int notifyRetryTimes = 3;

    @Getter
    @Setter
    private int notifyRetryBackoffMillis = 500;

    @Getter
    @Setter
    private int notifyTempExecutorPoolSize = OsUtils.getCpuCount() * 3;

    @Getter
    @Setter
    private int notifyTempExecutorQueueSize = 4000;
    @Getter
    @Setter
    private int notifyTempDataIntervalMillis = 500;

    @Setter
    @Getter
    private int rpcTimeoutMillis = 3000;

    private CommonConfig commonConfig;

    private volatile Collection<String> metaAddresses = null;

    @Setter
    @Getter
    private int getDataExecutorMinPoolSize = OsUtils.getCpuCount() * 3;

    @Setter
    @Getter
    private int getDataExecutorMaxPoolSize = OsUtils.getCpuCount() * 3;

    @Getter
    @Setter
    private int getDataExecutorQueueSize = 20000;

    @Setter
    @Getter
    private long getDataExecutorKeepAliveTime = 60;

    @Setter
    @Getter
    private int publishExecutorMinPoolSize = OsUtils.getCpuCount() * 3;

    @Setter
    @Getter
    private int publishExecutorMaxPoolSize = OsUtils.getCpuCount() * 3;

    @Setter
    @Getter
    private int publishExecutorQueueSize = 10000;

    @Setter
    @Getter
    private volatile int sessionLeaseSecs = 30;
    @Setter
    @Getter
    private int sessionLeaseCheckIntervalSecs = 5;
    @Getter
    @Setter
    private int sessionLeaseCleanDeadlineSecs = 5;

    @Setter
    @Getter
    private int datumCompactDelaySecs = 60 * 3;

    @Setter
    @Getter
    private int slotLeaderSyncSessionExecutorThreadSize = OsUtils.getCpuCount() * 3;

    @Setter
    @Getter
    private int slotLeaderSyncSessionExecutorQueueSize = 40000;
    @Setter
    @Getter
    private volatile int slotLeaderSyncSessionIntervalSecs = 6;
    @Setter
    @Getter
    private volatile int slotSyncAppRevisionIntervalSecs = 6;

    @Setter
    @Getter
    private volatile int slotSyncServiceMappingIntervalSecs = 6;


    @Setter
    @Getter
    private int slotFollowerSyncLeaderExecutorThreadSize = OsUtils.getCpuCount();

    @Setter
    @Getter
    private int slotFollowerSyncLeaderExecutorQueueSize = 10000;

    @Setter
    @Getter
    private volatile int slotFollowerSyncLeaderIntervalSecs = 180;

    // the publisher.digest if len(registerId/uuid+long+long), 50bytes
    @Setter
    @Getter
    private volatile int slotSyncPublisherDigestMaxNum = 4000;

    @Setter
    @Getter
    private volatile int slotSyncPublisherMaxNum = 512;


    @Getter
    @Setter
    private int slotSyncRequestExecutorMinPoolSize = OsUtils.getCpuCount() * 3;


    @Getter
    @Setter
    private int slotSyncRequestExecutorMaxPoolSize = OsUtils.getCpuCount() * 3;


    @Getter
    @Setter
    private int slotSyncRequestExecutorQueueSize = 1000;

    @Getter
    @Setter
    private int metaNodeExecutorPoolSize = OsUtils.getCpuCount() * 3;

    @Getter
    @Setter
    private int metaNodeExecutorQueueSize = 1000;


    @Getter
    @Setter
    private int schedulerHeartbeatIntervalSecs = 1;

    @Getter
    @Setter
    private boolean enableTestApi = false;

    @Getter
    @Setter
    private int cacheDigestIntervalMinutes = 15;

    @Getter
    @Setter
    private int cacheCountIntervalSecs = 60;

    @Getter
    @Setter
    private int lowWaterMark = 1024 * 256;
    @Getter
    @Setter
    private int highWaterMark = 1024 * 288;

    @Getter
    @Setter
    private int migratingMaxSecs = 40;
    @Getter
    @Setter
    private int migratingMaxRetry = 15;
    @Getter
    @Setter
    private int migratingMaxUnavailable = 1;

    private int systemPropertyIntervalMillis = 3000;

    @Getter
    @Setter
    private boolean gracefulShutdown = false;


    public ServerConfig(CommonConfig commonConfig) {
        this.commonConfig = commonConfig;
    }

    public boolean isLocalDataCenter(String dataCenter) {
        return commonConfig.getDataCenter().equals(dataCenter);
    }

    public String getDataCenter() {
        return commonConfig.getDataCenter();
    }


    public Collection<String> getMetaServerAddresses() {
        final Collection<String> addresses = metaAddresses;
        if (addresses != null) {
            return addresses;
        }
        metaAddresses = ServerEnv.getMetaAddresses(commonConfig.getMetaNode(), commonConfig.getDataCenter());
        return metaAddresses;
    }


    @Override
    public int getSystemPropertyIntervalMillis() {
        return systemPropertyIntervalMillis;
    }

}
